import axios, { type CancelTokenSource } from "axios";
import type { CustomRequestConfig } from "./types";

/**
 * 请求取消控制器
 * 用于管理请求的取消操作，防止重复请求
 */
export class CancelController {
  private pendingRequests: Map<string, CancelTokenSource> = new Map();

  /**
   * 生成请求的唯一标识
   * @param config 请求配置
   * @returns 请求唯一标识
   */
  private getRequestKey(config: CustomRequestConfig): string {
    const { method = "get", url = "", params, data } = config;
    return `${method.toLowerCase()}_${url}_${JSON.stringify(params || {})}_${JSON.stringify(data || {})}`;
  }

  /**
   * 添加请求到待处理队列
   * @param config 请求配置
   * @returns 更新后的请求配置
   */
  public addRequest(config: CustomRequestConfig): CustomRequestConfig {
    if (config.ignoreRepeat) {
      return config;
    }

    const requestKey = this.getRequestKey(config);

    // 如果存在相同请求，则取消之前的请求
    if (this.pendingRequests.has(requestKey)) {
      this.removeRequest(requestKey);
    }

    const source = axios.CancelToken.source();
    config.cancelToken = source.token;
    this.pendingRequests.set(requestKey, source);

    return config;
  }

  /**
   * 根据请求标识移除请求
   * @param key 请求标识
   */
  public removeRequest(key: string): void {
    if (this.pendingRequests.has(key)) {
      const source = this.pendingRequests.get(key)!;
      source.cancel("请求已取消");
      this.pendingRequests.delete(key);
    }
  }

  /**
   * 根据请求配置移除请求
   * @param config 请求配置
   */
  public removeRequestByConfig(config: CustomRequestConfig): void {
    const requestKey = this.getRequestKey(config);
    this.removeRequest(requestKey);
  }

  /**
   * 取消所有请求
   */
  public cancelAllRequests(): void {
    this.pendingRequests.forEach(source => {
      source.cancel("所有请求已取消");
    });
    this.pendingRequests.clear();
  }
}
